/***************************************************************************
 *   Copyright (C) 2008 by Ryszard Krol   *
 *   rysiek.krol@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "imagereader.h"
#include "picturemanager.h"
#include "updateiconevent.h"
#include "picturelistwidgetitem.h"
#include "updatestatusbarevent.h"
#include "rexifdata.h"
#include "utils.h"

#include <QDir>
#include <QFileInfoList>
#include <QFileInfo>
#include <QListWidgetItem>
#include <QApplication>
#include <QFile>
#include <QList>
#include <QListIterator>
#include <zlib.h>





/**
* Konstruktor
 */
ImageReader::ImageReader ( PictureManager *manager, QDir *dir )
        : QThread()
{
	this->action = ImageReader::ReadDir;
    this->manager = manager;
    this->dir = dir;
    this->isActive = true;
    this->readingDir = true;
    sendIconGenerationCompleateEvent = false;
    this->start ( QThread::LowPriority );
}

/**
* Destruktor
*/
ImageReader::~ImageReader()
{
    delete dir;
}

void ImageReader::run()
{

    while (true)
    {
        mutex.lock();
        this->isActive = true;
        mutex.unlock();
        this->readingDir = true;
        this->generateItems();
        this->setIsActive(false);
        if (this->manager->getListWidget()->count()>0)
        {
            this->waitMutex.lock();
            this->setAction(ImageReader::ReadDir);
            this->readDirCondition.wait(&this->waitMutex);
            this->waitMutex.unlock();
        }
    }
}

/**
* Generates item from files in directory
*/
void ImageReader::generateItems()
{

    qRegisterMetaType<QModelIndex> ( "QModelIndex" );


    //lista wskaznikow do sortowania
    QList<PictureListWidgetItem*> *lista = new QList<PictureListWidgetItem*>();
    if (this->action==ImageReader::ReadDir)
    {
        QFileInfoList fileInfoList = this->dir->entryInfoList (QDir::Dirs, QDir::Name);
        for ( int i = 0; i<fileInfoList.size() ;i++ )
        {
            if (!this->isActive)
            {
                this->sendIconGenerationCompleateEvent = true;
                break;
            }
            QFileInfo fileInfo = fileInfoList.at ( i );
            if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
            {
                if (fileInfo.fileName() == "..")
                {
                    new PictureListWidgetItem (fileInfo, ".. (up)" ,this->manager->getListWidget() );
                }
            }
            else
            {
                new PictureListWidgetItem (fileInfo,this->manager->getListWidget() );
            }
        }
        QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ListRefreshNeeded ) ) );

        //Dodawanie plikow do listy
        QStringList filters;
        filters << "*.jpg" << "*.png" << "*.bmp"<<"*.jpeg"<<"*.JPG"<<"*.JPEG";
        fileInfoList = this->dir->entryInfoList ( filters,QDir::Files,QDir::Name );

        //Wypelnianie listy wskaznikow
        for ( int i = 0; i<fileInfoList.size();i++ )
        {
            if (!this->isActive)
            {
                this->sendIconGenerationCompleateEvent = true;
                break;
            }
            QFileInfo fileInfo = fileInfoList.at ( i );
            lista->append(new PictureListWidgetItem (fileInfo));
        }
    } else if(this->action==ImageReader::SortItems) {
	lista = this->widgetList;
    
    }
    if (lista->count()>0)QApplication::postEvent ( manager, new UpdateStatusBarEvent( new QString(QString::number(lista->count()) + " items")));
    //sortowanie listy
    this->sortItems(lista, 0, lista->count() -1);
    //wypelnianie QListWidgetu posortowanymi elementami
    QListIterator<PictureListWidgetItem*> listaIterator(*lista);
    while (listaIterator.hasNext())
    {
        if (!this->isActive)
        {
            this->sendIconGenerationCompleateEvent = true;
            break;
        }
        this->manager->getListWidget()->addItem(listaIterator.next());
    }
    this->readingDir = false;
    //Sygnal do zrefreshowania listy
    QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ListRefreshNeeded )));
    for ( int i = 0; i<this->manager->getListWidget()->count();i++ )
    {
        if (!this->isActive)
        {
            // sendIconGenerationCompleateEvent is used to start reader once more, when user change dir before
            // reader can generates all icons
            this->sendIconGenerationCompleateEvent = true;
            break;
        }
        PictureListWidgetItem *item = dynamic_cast<PictureListWidgetItem*> ( this->manager->getListWidget()->item ( i ) );
        QFileInfo file = item->getFile();
        UpdateIconEvent *event = new UpdateIconEvent (new QImage(Utils::generateIcon ( item->getFile() )),item );
        if (this->isActive)QApplication::postEvent ( manager, event );
    }
    delete lista;

    if (this->sendIconGenerationCompleateEvent == true)
    {
        this->sendIconGenerationCompleateEvent = false;
        if (this->isActive)QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::iconGenerationCompleateEvent ) ));
    }

}

/**
* Sorts Widget List
*/
void ImageReader::sortItems ( QList<PictureListWidgetItem*> *lista, int beg, int end )
{
    if ( beg<end )
    {
        int m=beg;
        for ( int i=beg+1;i<=end;i++ )
        {
            if ( this->compareItems(lista->at ( i ), lista->at ( beg )) ) lista->swap ( ++m,i );
        }
        lista->swap ( beg,m );
        this->sortItems ( lista,beg,m-1 );
        this->sortItems ( lista,m+1,end );
    }
}


/**
* Sets  ImageReader Thread  active variable
*/
void ImageReader::setIsActive ( bool theValue )
{
    mutex.lock();
    isActive = theValue;
    mutex.unlock();
}

/**
* Returns current Directory
*/
QDir* ImageReader::getDir() const
{
    return dir;
}

/**
* Sets current Directory
*/
void ImageReader::setDir ( QDir* theValue )
{
    mutex.lock();
    dir = theValue;
    mutex.unlock();
}

/**
* returns is ImageReader Thread active
*/
bool ImageReader::active()
{
    bool w;
    mutex.lock();
    w = this->isActive;
    mutex.unlock();
    return w;
}

/**
* Returns true, if items should be swaped by sort algorytm
*/
bool ImageReader::compareItems(PictureListWidgetItem * firstItem, PictureListWidgetItem * secondItem)
{
    switch (this->manager->getItsProperty()->getSortMethod())
    {
    case Property::ByCommentDate:
        if ( (firstItem->isDate() && secondItem->isDate()) && ( firstItem->getDateTime() <secondItem->getDateTime() ) )
            return true;
        break;
    case Property::ByFileName:
        if ( firstItem->getFile().fileName() < secondItem->getFile().fileName() ) return true;
        break;

    }
    return false;
}


bool ImageReader::getReadingDir() const
{
    return readingDir;
}




void ImageReader::setAction(const ImageReader::Action& theValue)
{
    action = theValue;
}


void ImageReader::setWidgetList(QList< PictureListWidgetItem * >* theValue)
{
    widgetList = theValue;
}
